package plan;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

import util.Interval;
import auftrag.Operation;
import auftrag.Resource;

public class Plan {
	private ArrayList<Belegung> mBelegungen = new ArrayList<Belegung>();
	
	private HashMap<Resource, ArrayList<Interval>> mResourceBelegungen = new HashMap<Resource, ArrayList<Interval>>();
	private HashMap<Operation, Interval> mPlannedOperations = new HashMap<Operation, Interval>();
	
	public boolean addBelegung(Belegung b){
		if(b.getOperation().getPreviousOperation() != null && !mPlannedOperations.containsKey(b.getOperation().getPreviousOperation()))
			return false;
		if(mResourceBelegungen.containsKey(b.getResource())){
			boolean bOverlaps = false;
			for(Interval i: mResourceBelegungen.get(b.getResource())){
				if(i.overlapsWith(b.getInterval())){
					bOverlaps = true;
					break;
				}
				if(i.compareTo(b.getInterval()) == 1)
					break;
			}
			if(!bOverlaps){
				mResourceBelegungen.get(b.getResource()).add(b.getInterval());
				Collections.sort(mResourceBelegungen.get(b.getResource()));
				mPlannedOperations.put(b.getOperation(), b.getInterval());
				
				mBelegungen.add(b);
				Collections.sort(mBelegungen);
				return true;
			}
			else
				return false;
		} else {
			ArrayList<Interval> tmpList = new ArrayList<Interval>();
			tmpList.add(b.getInterval());
			mResourceBelegungen.put(b.getResource(), tmpList);
			mPlannedOperations.put(b.getOperation(), b.getInterval());
			
			mBelegungen.add(b);
			Collections.sort(mBelegungen);
			return true;
		}
	}
	
	public void print(){
		for(Belegung b: mBelegungen){
			System.out.println(b.getResource()+" - ("+b.getInterval()+") - "+b.getOperation());
		}
	}
	
	public boolean isPlanned(Operation o){
		if(o!= null && mPlannedOperations.containsKey(o))
			return true;
		return false;
	}
	
	public ArrayList<Operation> getOperations(){
		ArrayList<Operation> tmp = new ArrayList<Operation>();
		tmp.addAll(mPlannedOperations.keySet());
		return tmp;
	}
	
	public Interval getUnoccupiedInterval(Operation o, Resource r, int d){
		int n;
		if(o.getPreviousOperation() != null && !mPlannedOperations.containsKey(o.getPreviousOperation())){
			return null;
		}
		else if(o.getPreviousOperation() == null)
			n = 0;
		else
			n = mPlannedOperations.get(o.getPreviousOperation()).getEnd();
		
		Interval tmpCompare = new Interval(n, n+d);
		
		if(!mResourceBelegungen.containsKey(r))
			return tmpCompare;
		
		boolean bIntervalFound = false;
		while(!bIntervalFound){
			bIntervalFound = true;
			for(Interval i: mResourceBelegungen.get(r)){
				if(i.overlapsWith(tmpCompare)){
					bIntervalFound = false;
					tmpCompare.moveTo(i.getEnd());
					break;
				} else if(i.compareTo(tmpCompare) == 1)
					break;
			}
		}
		return tmpCompare;
	}
	
	public ArrayList<Belegung> getBelegungen(){
		return mBelegungen;
	}
	
	public int getEndDate(){
		int max = 0;
		for(Belegung b:mBelegungen)
			if(b.getInterval().getEnd() > max)
				max = b.getInterval().getEnd();
		return max;
	}
}
